//-----------------------------------------
//	PhongTexture
//-----------------------------------------

//------------------
//--- Parameters ---
shared float4x4 World;
shared float4x4 View;
shared float4x4 Projection;
shared float3 cameraPosition;

//light properties
shared float3 lightPosition;
shared float4 ambientLightColor;
shared float4 diffuseLightColor;
shared float4 specularLightColor;

//material properties
shared float specularPower = 16;
shared float specularIntensity = 1;

bool TextureEnabled;
texture Texture;

sampler ModelTextureSampler = sampler_state
{
    Texture = <Texture>;

    MinFilter = Linear;
    MagFilter = Linear;
    MipFilter = Linear;
    AddressU = Clamp;
    AddressV = Clamp;
};

//------------------
//--- Structures ---
struct VertexShaderInput
{
	float4 Position : POSITION;
	float3 Normal : NORMAL;
	float2 TextureCoordinate : TEXCOORD0;
};

struct VertexShaderOutput 
{
    float4 Position : POSITION;
    float2 TextureCoordinate : TEXCOORD0;
	float3 WorldNormal : TEXCOORD1;
    float3 WorldPosition : TEXCOORD2;
};

struct PixelShaderInput
{
	float2 TextureCoordinate : TEXCOORD0;
    float3 WorldNormal : TEXCOORD1;
    float3 WorldPosition : TEXCOORD2;
};

//--------------------
//--- VertexShader ---
VertexShaderOutput PerPixelDiffuseVS(VertexShaderInput input)
{
    VertexShaderOutput output;

    //transform the input position to the output
    output.Position = mul(mul(mul(input.Position, World),View),Projection);

    output.WorldNormal =  mul(input.Normal, World);
    float4 worldPosition =  mul(input.Position, World);
    output.WorldPosition = worldPosition / worldPosition.w;

	output.TextureCoordinate = input.TextureCoordinate;
	
    //return the output structure
    return output;
}

//-------------------
//--- PixelShader ---
float4 DiffuseAndPhongPS(PixelShaderInput input) : COLOR
{
	//calculate per-pixel diffuse
	float3 directionToLight = normalize(lightPosition - input.WorldPosition);
    float diffuseIntensity = saturate( dot(directionToLight, input.WorldNormal));
    float4 diffuse = diffuseLightColor * diffuseIntensity;

    //calculate Phong components per-pixel
    float3 reflectionVector = normalize(reflect(-directionToLight, input.WorldNormal));
    float3 directionToCamera = normalize(cameraPosition - input.WorldPosition);
     
    //calculate specular component
    float4 specular = specularLightColor * specularIntensity * 
                       pow(saturate(dot(reflectionVector, directionToCamera)), 
                           specularPower);
      
    float4 outputColor;
     
    if(TextureEnabled)
		outputColor = (specular  + diffuse + ambientLightColor) * tex2D(ModelTextureSampler, input.TextureCoordinate);
    else
		outputColor = specular  + diffuse + ambientLightColor;		
     
    return outputColor;
}

//------------------
//--- Techniques ---
technique PerPixelDiffuseAndPhong
{
    pass P0
    {
          VertexShader = compile vs_2_0 PerPixelDiffuseVS();
          PixelShader = compile ps_2_0 DiffuseAndPhongPS();
    }
}